# -*- coding: utf-8 -*-

"""
Module implementing MainWindow_slots.
"""
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import pyqtSlot, QModelIndex, Qt, pyqtSignal
from PyQt5.QtGui import QBrush, QColor, QStandardItemModel
from PyQt5.QtWidgets import QMainWindow, QFileDialog, QTableWidgetItem, QMessageBox, QDialog
from Ui_MainWindow_csv_modify import Ui_MainWindow
from Ui_Replace_Dialog import Ui_Dialog
import Ui_Matching_Modes
import sys
import csv
import os
import time
import traceback
import logging
# logging.basicConfig(filename="Debug.log", level=logging.DEBUG, format=" [%(asctime)s] - [%(levelname)s] - [%(message)s]")
logging.basicConfig(level=logging.DEBUG, format=" [%(asctime)s] - [%(levelname)s] - [%(message)s]")
# logging.disable(logging.DEBUG)

class MainWindow_slots(QMainWindow, Ui_MainWindow):
    Signal_AddNextButton = pyqtSignal() # 主窗体发送给Replace_Dialog添加按钮
    def __init__(self, parent=None):
        super(MainWindow_slots, self).__init__(parent)
        self.setupUi(self)
        # self.setFocusPolicy(QtCore.Qt.StrongFocus) # 为了接收 键盘输入 否则再键入字母时 keyPressEvent()事件函数不响应
        # self.tableWidget.setFocusPolicy(QtCore.Qt.StrongFocus)
        self.UI_init()

    # 界面布局初始化
    def UI_init(self):
        self.pushButton_6.setVisible(False) # 下一个按钮隐藏
        self.label_3.setVisible(False)
        self.pushButton_7.setVisible(False)
        self.pushButton_8.setVisible(False)
        self.lineEdit_2.setVisible(False)

    # 点击 选择文件
    @pyqtSlot()
    def on_action_triggered(self):
        csv_file_address = QFileDialog.getOpenFileName(self, "选择.csv文件:", "", "CSV(*.csv)")
        csv_file_address = csv_file_address[0]
        Global_Variables.G_save_file_address_name = csv_file_address.split(".")[:-1] # 获取csv文件路径 包含文件名 不包含.csv
        Global_Variables.G_save_file_address_name = ".".join(Global_Variables.G_save_file_address_name) # 由于split可能会生成list，再用 "."join() 进行保护
        try:
            self.read_csv_file(p_csv_file_address=csv_file_address)
        except:
            log = "【ERROR:】打开文件错误...\n详细信息:" + traceback.format_exc()
            print(log)
            logging.error(log)

    # 点击 关于
    @pyqtSlot()
    def on_action_2_triggered(self):
        QMessageBox.about(self, "说明", "1.文件保存时会自动备份源文件，格式为“原文件名+日期+时间.csv”。新保存的文件不会覆盖原文件。")

    # 打开 设置匹配模式 菜单
    @pyqtSlot()
    def on_action_3_triggered(self):
        try:
            matching_modes_dialog = Matching_Modes_Dialog() # 实例化的对象和类不能同名
            matching_modes_dialog.exec_()
        except:
            print(traceback.format_exc())

    # 数据改变
    @pyqtSlot(QTableWidgetItem)
    def on_tableWidget_itemChanged(self, item):
        # print(item.row() + 1) # 返回行数
        # print(item.column() + 1) # 返回列数
        # print(item.data(0)) # 返回值item.data(int role) role为显示单元格的数据类型 详见：http://doc.qt.io/qt-5/qt.html#ItemDataRole-enum
        # 0 - 单元格内容
        pass

    # 点击单元格
    @pyqtSlot(QTableWidgetItem)
    def on_tableWidget_itemClicked(self, item):
        pass

    # 点击确认按钮
    @pyqtSlot()
    def on_pushButton_2_clicked(self):
        # 先备份原文件
        try:
            backup_original_file()
        except:
            log = "【ERROR:】备份源文件失败...\n相信信息:" + traceback.format_exe()
            print(log)
            logging.error(log)
        # 生成新的csv文件
        try:
            row_num, colmun_num = self.tableWidget.rowCount(), self.tableWidget.columnCount() # 获取 tableWidget 中的行数与列数
            with open(Global_Variables.G_save_file_address_name + ".csv", "w", newline="") as csv_write_file:
                csv_file_writer = csv.writer(csv_write_file)
                # 获取表头
                field_list = []
                for i in range(colmun_num):
                    field_list.append(self.tableWidget.horizontalHeaderItem(i).data(0))
                csv_file_writer.writerow(field_list)
                # 获取单元格
                for i in range(row_num):
                    row_list = []
                    for j in range(colmun_num):
                        try:
                            item_value = self.tableWidget.item(i, j).data(0)
                            # 将显示的44-, 转换为24-↑ 进行存储
                            item_value = convert_special_characters_org_to_new(original_str=item_value, org_ascii=44, new_ascii=24)
                            # ascii 34-" 双引号特殊转换
                            item_value = convert_special_characters_org_to_new(original_str=item_value, org_ascii=34, new_ascii=1)
                        except:
                            log = "【ERROR:】字符转换失败...\n详细信息:" + traceback.format_exc()
                            print(log)
                            logging.error(log)

                        try:
                            row_list.append(item_value)
                        except:
                            log = "【ERROR:】row_list.append(item_value) 失败...\n详细信息:" + traceback.format_exc()
                            print(log)
                            logging.error(log)
                            row_list.append("NULL")
                    csv_file_writer.writerow(row_list) # 写入item 一次写入一行数据
            # 处理保存后的文件
            with open(Global_Variables.G_save_file_address_name + ".csv", "r") as read_file:
                str_file = read_file.read()
                # 将之前转换过的双引号重新转换 34-"
                # (处理解释:由于单元格中双引号在保存时会转义，导致与原数据不相符，因此在保存时先将双引号转换为其他字符，再在保存后的文件中遍历该字符再转化为双引号)
                str_file = convert_special_characters_org_to_new(original_str=str_file, org_ascii=1, new_ascii=34)
            with open(Global_Variables.G_save_file_address_name + ".csv", "w") as write_file:
                write_file.write(str_file)
            QMessageBox.information(self, '提示', '保存成功', QMessageBox.Ok)
        except:
            log = "【ERROR:】保存csv文件失败...\n详细信息:" + traceback.format_exe()
            print(log)
            logging.error(log)

    # 点击插入按钮
    @pyqtSlot()
    def on_pushButton_3_clicked(self):
        try:
            column, row = self.tableWidget.selectedItems()[0].column(), self.tableWidget.selectedItems()[0].row() # tableWidget.selectedItems() 返回list (被选中的单元格的指针)
            self.tableWidget.insertRow(row+1) # 槽信号，在指定行 插入空行
            # begin 新增行默认生成item并插入空字符 这么做的原因是否则在对新增行进行insertRow时会报错 “list index out of range”
            column_num = self.tableWidget.columnCount() # 返回视图的列数
            for i in range(column_num):
                item_value = ""
                item = QTableWidgetItem(item_value)
                self.tableWidget.setItem(row+1, i, item) # setItem 一次setitem只能设置一个item，设置后item需再次赋值才可以 可能是根据id(item)进行判断，如果下一次的id和之前id相同则不在执行setitem
            # end 新增行默认插入空格
            logging.debug("行：{row}，列：{column}".format(row=row + 1, column=column + 1))
            # self.tableWidget.setRowCount(self.tableWidget.rowCount() + 1)
        except:
            log = "【ERROR:】插入失败...\n详细信息:" + traceback.format_exc()
            print(log)
            logging.error(log)

    # 点击删除按钮
    @pyqtSlot()
    def on_pushButton_4_clicked(self):
        try:
            column, row = self.tableWidget.selectedItems()[0].column(), self.tableWidget.selectedItems()[0].row() # tableWidget.selectedItems() 返回list (被选中的单元格的指针)
            self.tableWidget.removeRow(row) # 槽信号，在指定行 删除该行
            logging.debug("行：{row}，列：{column}".format(row=row + 1, column=column + 1))
            # self.tableWidget.setRowCount(self.tableWidget.rowCount() + 1)
        except:
            log = "【ERROR:】删除失败...\n详细信息:" + traceback.format_exc()
            print(log)
            logging.error(log)

    # 点击搜索按钮
    @pyqtSlot()
    def on_pushButton_5_clicked(self):
        # 恢复tableWidget的样式
        self.tableWidget_style_init()
        # 在tableWidget搜索并显示
        self.searchDate(p_search_for_date=self.lineEdit.text())

    # 点击下一个按钮
    @pyqtSlot()
    def on_pushButton_6_clicked(self):
        # 下一个查询
        self.searchNext()

    # 点击全部替换按钮
    @pyqtSlot()
    def on_pushButton_7_clicked(self):
        # 全部替换
        self.replaceAllDate(p_replace_str=self.lineEdit_2.text()) # 替换的内容

    # 点击替换按钮
    @pyqtSlot()
    def on_pushButton_8_clicked(self):
        # 替换数据
        self.replaceDate(self.lineEdit_2.text())

    # 点击Replace_Dialog 搜索 按钮
    @pyqtSlot(str)
    def slot_searchDate(self, dateStr):
        # 恢复tableWidget的样式
        self.tableWidget_style_init()
        # 在tableWidget搜索并显示
        self.searchDate(p_search_for_date=dateStr)

    # 点击Replace_Dialog 下一个 按钮
    @pyqtSlot()
    def slot_searchNext(self):
        # 下一个查询
        self.searchNext()

    # 点击Replace_Dialog 替换 按钮
    @pyqtSlot(str)
    def slot_replaceDate(self, p_replace_str):
        self.replaceDate(p_replace_str=p_replace_str)

    # 点击Replace_Dialog 全部替换 按钮
    @pyqtSlot(str)
    def slot_replaceAllDate(self, p_replace_str):
        self.replaceAllDate(p_replace_str=p_replace_str)

    # 读取csv文件并展示
    def read_csv_file(self, p_csv_file_address):
        csv_file_address = p_csv_file_address
        # 获取模板
        self.set_tableWidget_style(p_csv_file_address=csv_file_address)
        self.label.setText("CSV文件：" + csv_file_address.split("/")[-1])
        return None

    # 设置 tableWidget 显示
    def set_tableWidget_style(self, p_csv_file_address):
        csv_file_address = p_csv_file_address
        row_num, colmun_num = get_csv_row_column_num(p_csv_file_address=csv_file_address)
        self.tableWidget.setRowCount(row_num - 1) # 设置 行数 减去表头
        self.tableWidget.setColumnCount(colmun_num) # 设置 列数
        with open(csv_file_address, "r", encoding="utf-8") as csv_file: # TODO:要修改编码格式，按照文件的编码格式打开
            csv_file_reader = csv.reader(csv_file)
            csv_file_data = list(csv_file_reader)  # 将数据转换为list格式 可以通过data[行][列]来获取数据
        # 遍历csv数据生成 item
        for i in range(row_num):
            self.tableWidget.setRowHeight(i, 20) # 设置行高
            for j in range(colmun_num):
                try:
                    item_value = csv_file_data[i][j]
                except:
                    item_value = " "
                # 将csv文件中存储的 44-↑ ， 以24-, 显示
                item_value = convert_special_characters_org_to_new(original_str=item_value, org_ascii=24, new_ascii=44)
                item = QTableWidgetItem(item_value)
                self.tableWidget.setItem(i-1, j, item)
        # 获取表头
        field_list = csv_file_data[0]
        self.tableWidget.setHorizontalHeaderLabels(field_list)

    # 恢复 tableWidget 显示样式
    def tableWidget_style_init(self):
        try:
            row, column = self.tableWidget.rowCount(), self.tableWidget.columnCount()
            logging.debug("行{0}，列{1}".format(row, column))
            for i in range(row):
                for j in range(column):
                    item = self.tableWidget.item(i, j)
                    item.setBackground(QBrush(QColor(250, 250, 250)))
        except:
            log = "【ERROR:】tableWidget显示失败...\n详细信息" + traceback.format_exc()
            print(log)
            logging.error(log)
        return None

    # 在tableWidget搜索并显示
    def searchDate(self, p_search_for_date):
        Global_Variables.G_next_count = 0  # 循环计数清0
        Global_Variables.G_finditems_row_list = []  # 循环计数清0
        Global_Variables.G_finditems_column_list = []  # 循环计数清0
        try:
            Global_Variables.G_search_text = p_search_for_date
            logging.debug(Global_Variables.G_search_text)
            finditems_list = self.tableWidget.findItems(Global_Variables.G_search_text,
                                                        Global_Variables.G_match_flag)  # 包含模式 搜索 返回list QTableWidgetItem对象
            if finditems_list == []:
                QMessageBox.information(self, "提示:", "未找到:{0}".format(Global_Variables.G_search_text), QMessageBox.Ok)
            else:
                self.pushButton_6.setVisible(True)  # 显示下一个按钮
                self.Signal_AddNextButton.emit() # 发送给Replace_Dialog对话框新增按钮
                for Global_Variables.G_finditems_list_no, item in enumerate(finditems_list):  # 高亮显示搜索到的内容
                    item.setBackground(QBrush(QColor(255, 255, 0)))  # 黄色
                    Global_Variables.G_finditems_row_list.append(item.row())
                    Global_Variables.G_finditems_column_list.append(item.column())
                # 定位到找到的第一个单元格，并设置为绿色
                self.tableWidget.item(Global_Variables.G_finditems_row_list[Global_Variables.G_next_count],
                                      Global_Variables.G_finditems_column_list[
                                          Global_Variables.G_next_count]).setBackground(QBrush(QColor(0, 255, 0)))  # 绿色
                self.tableWidget.verticalScrollBar().setSliderPosition(
                    Global_Variables.G_finditems_row_list[Global_Variables.G_next_count])  # 定位光标位置
                self.tableWidget.horizontalScrollBar().setSliderPosition(
                    Global_Variables.G_finditems_column_list[Global_Variables.G_next_count])  # 定位光标位置
                QMessageBox.information(self, "提示:", "共找到{0}处".format(len(finditems_list)), QMessageBox.Ok)
                logging.debug(
                    "位置行{0}，列{1}".format(Global_Variables.G_finditems_row_list, Global_Variables.G_finditems_column_list))
        except:
            log = "【ERROR:】搜索失败...\n详细信息:" + traceback.format_exc()
            logging.error(log)

    # 下一个查询
    def searchNext(self):
        try:
            logging.debug("Global_Variables.G_next_count:" + str(Global_Variables.G_next_count))
            if Global_Variables.G_next_count >= len(Global_Variables.G_finditems_row_list) - 1:
                QMessageBox.information(self, '提示', '已全部查完...', QMessageBox.Ok)
            else:
                Global_Variables.G_next_count += 1
                self.tableWidget.item(Global_Variables.G_finditems_row_list[Global_Variables.G_next_count], Global_Variables.G_finditems_column_list[Global_Variables.G_next_count]).setBackground(QBrush(QColor(0, 255, 0))) # 绿色
                self.tableWidget.verticalScrollBar().setSliderPosition(Global_Variables.G_finditems_row_list[Global_Variables.G_next_count]) # 定位光标位置
                self.tableWidget.horizontalScrollBar().setSliderPosition(Global_Variables.G_finditems_column_list[Global_Variables.G_next_count]) # 定位光标位置
        except:
            log = "【ERROR:】向下匹配失败...\n详细信息:" + traceback.format_exc()
            print(log)
            logging.error(log)
        return None

    # 替换数据
    def replaceDate(self, p_replace_str):
        if Global_Variables.G_finditems_row_list == [] or Global_Variables.G_finditems_row_list == []:
            QMessageBox.information(self, "提示:", "未找到需要替换的内容", QMessageBox.Ok)
        else:
            try:
                logging.debug("行{0}，列{1}".format(Global_Variables.G_finditems_row_list[Global_Variables.G_next_count],
                                                 Global_Variables.G_finditems_column_list[Global_Variables.G_next_count]))
                item_value = p_replace_str # 替换的内容
                item = QTableWidgetItem(item_value)
                self.tableWidget.setItem(Global_Variables.G_finditems_row_list[Global_Variables.G_next_count], Global_Variables.G_finditems_column_list[Global_Variables.G_next_count], item)
            except:
                log = "【ERROR:】替换错误...\n详细信息:" + traceback.format_exc()
                logging.error(log)

    # 全部替换
    def replaceAllDate(self, p_replace_str):
        count = 0
        if Global_Variables.G_finditems_row_list == [] or Global_Variables.G_finditems_row_list == []:
            QMessageBox.information(self, "提示:", "未找到需要替换的内容", QMessageBox.Ok)
        else:
            try:
                logging.debug("行{0}".format(Global_Variables.G_finditems_row_list))
                logging.debug("列{0}".format(Global_Variables.G_finditems_column_list))
                for i, j in zip(Global_Variables.G_finditems_row_list, Global_Variables.G_finditems_column_list):
                    item_value = p_replace_str
                    item = QTableWidgetItem(item_value)
                    logging.debug("行{0}，列{1}".format(i, j))
                    self.tableWidget.setItem(i, j, item)
                    count += 1
                QMessageBox.information(self, "提示:", "替换完成，共替换{0}处".format(count), QMessageBox.Ok)
            except:
                log = "【ERROR:】替换错误...\n详细信息:" + traceback.format_exc()
                logging.error(log)

    # 暂时理解为，相应键盘事件的槽函数
    def keyPressEvent(self, event):
        try:
            if (event.modifiers() == QtCore.Qt.ControlModifier) and (event.key() == QtCore.Qt.Key_R): # Ctrl+R
                print("Ctrl+R")
                # 暂未解决 两个类直接的对象交互
                replace_dialog = Replace_Dialog() # 实例化的对象和类不能同名
                replace_dialog.Signal_OneParameter.connect(self.slot_searchDate) # 不要填写() 和 里面的参数
                replace_dialog.pushButton_3.clicked.connect(self.slot_searchNext)
                replace_dialog.Signal_Replace_Date.connect(self.slot_replaceDate)
                replace_dialog.Signal_Replace_ALLDate.connect(self.slot_replaceAllDate)
                self.Signal_AddNextButton.connect(replace_dialog.add_button)
                replace_dialog.exec_()
                # 主界面显示搜索框
                if Global_Variables.G_ctrl_r_flag == 0:
                    Global_Variables.G_ctrl_r_flag = 1
                    self.label_3.setVisible(True)
                    self.pushButton_7.setVisible(True)
                    self.pushButton_8.setVisible(True)
                    self.lineEdit_2.setVisible(True)
                elif Global_Variables.G_ctrl_r_flag == 1:
                    Global_Variables.G_ctrl_r_flag = 0
                    self.label_3.setVisible(False)
                    self.pushButton_7.setVisible(False)
                    self.pushButton_8.setVisible(False)
                    self.lineEdit_2.setVisible(False)
        except:
            logging.error(traceback.format_exc())




# 替换 对话框
class Replace_Dialog(QDialog, Ui_Dialog):
    """
    Class documentation goes here.
    查找并替换字符
    """
    Signal_OneParameter = pyqtSignal(str)
    Signal_Replace_Date = pyqtSignal(str)
    Signal_Replace_ALLDate = pyqtSignal(str)
    def __init__(self, parent=None):
        super(Replace_Dialog, self).__init__(parent)
        self.setupUi(self)
        self.pushButton_3.setVisible(False) # 下一个和替换按钮初始隐藏，有查到数据时再显示
        self.pushButton_4.setVisible(False)

    # 点击 查找
    @pyqtSlot()
    def on_pushButton_clicked(self):
        self.Signal_OneParameter.emit(self.lineEdit.text())

    # 点击 全部替换
    @pyqtSlot()
    def on_pushButton_2_clicked(self):
        try:
            self.Signal_Replace_ALLDate.emit(self.lineEdit_2.text()) # 发送信号传递给主窗体 self.lineEdit_2().text()要替换的数据
        except:
            logging.error(traceback.format_exc())

    # 点击 替换
    @pyqtSlot()
    def on_pushButton_4_clicked(self):
        self.Signal_Replace_Date.emit(self.lineEdit_2.text()) # 发送信号传递给主窗体 self.lineEdit_2().text()要替换的数据

    # 显示 下一个和替换按钮
    @pyqtSlot()
    def add_button(self):
        self.pushButton_3.setVisible(True)
        self.pushButton_4.setVisible(True)

# 选择匹配模式 对话框
class Matching_Modes_Dialog(QDialog, Ui_Matching_Modes.Ui_Dialog):
    def __init__(self, parent=None):
        super(Matching_Modes_Dialog, self).__init__(parent)
        self.setupUi(self)
        self.show()

    # 点击保存按钮
    @pyqtSlot()
    def on_pushButton_clicked(self):
        if self.radioButton.isChecked():
            Global_Variables.G_match_flag = Qt.MatchExactly
        elif self.radioButton_2.isChecked():
            Global_Variables.G_match_flag = Qt.MatchFixedString
        elif self.radioButton_3.isChecked():
            Global_Variables.G_match_flag = Qt.MatchContains
        elif self.radioButton_4.isChecked():
            Global_Variables.G_match_flag = Qt.MatchStartsWith
        elif self.radioButton_5.isChecked():
            Global_Variables.G_match_flag = Qt.MatchEndsWith
        elif self.radioButton_6.isChecked():
            Global_Variables.G_match_flag = Qt.MatchCaseSensitive
        elif self.radioButton_7.isChecked():
            Global_Variables.G_match_flag = Qt.MatchWildcard
        elif self.radioButton_8.isChecked():
            Global_Variables.G_match_flag = Qt.MatchRegExp
        self.close()

    # 点击关闭按钮
    @pyqtSlot()
    def on_pushButton_2_clicked(self):
        self.close()

    # 打开对话框显示样式
    def show(self):
        if Global_Variables.G_match_flag == Qt.MatchExactly:
            self.radioButton.setChecked(True)
        elif Global_Variables.G_match_flag == Qt.MatchFixedString:
            self.radioButton_2.setChecked(True)
        elif Global_Variables.G_match_flag == Qt.MatchContains:
            self.radioButton_3.setChecked(True)
        elif Global_Variables.G_match_flag == Qt.MatchStartsWith:
            self.radioButton_4.setChecked(True)
        elif Global_Variables.G_match_flag == Qt.MatchEndsWith:
            self.radioButton_5.setChecked(True)
        elif Global_Variables.G_match_flag == Qt.MatchCaseSensitive:
            self.radioButton_6.setChecked(True)
        elif Global_Variables.G_match_flag == Qt.MatchWildcard:
            self.radioButton_7.setChecked(True)
        elif Global_Variables.G_match_flag == Qt.MatchRegExp:
            self.radioButton_8.setChecked(True)


# 全局变量
class Global_Variables():
    G_csv_file_address = " " # csv 文件地址
    G_search_text = " " # 搜索文本
    G_finditems_list_no = 0
    G_finditems_row_list = [] # 所有行坐标
    G_finditems_column_list = [] # 所有列坐标
    G_next_count = 0 # 记录定位下一个坐标的数字
    G_save_file_address_name = " " # 保存文件名
    G_match_flag = Qt.MatchContains # 搜索的匹配模式 默认为 3.包含模式搜索(系统默认)
    G_ctrl_r_flag = 0 # 替换模块控件显示标志 0未显示(默认) 1显示

# 返回 csv文件的行列数
def get_csv_row_column_num(p_csv_file_address): # 获取csv文件的行数和列数
    csv_file_address = p_csv_file_address
    row_num = 0
    colmun_num = 0
    with open(csv_file_address, "r", newline='', encoding = "ISO-8859-1") as csv_file:
        csv_file_reader = csv.reader(csv_file)
        logging.debug(type(csv_file_reader))
        for row in csv_file_reader:
            row_num += 1 # 获取csv行数
            if len(row) > colmun_num:
                colmun_num = len(row) # 获取最大列数
    return row_num, colmun_num

# 字符转换 通过ASCII码
def convert_special_characters_org_to_new(original_str, org_ascii, new_ascii):
    """
    :param original_str: 需要转换的字符串
    :param org_ascii: 需要转换的字符的ascii码
    :param new_ascii: 转换后字符的acii码
    :return: 返回一个新的字符串
    """
    new_str = ""
    # new_list = []
    for i in original_str:
        ascii_num = ord(i)  # "特殊字符↑"
        if ascii_num == org_ascii:
            i = chr(new_ascii)  # ","
        new_str += i  # 重新拼接成新的的字符串 此方法 效率低 待改进
    return new_str

# 先备份原文件
def backup_original_file():
    suffix_file_name = time.strftime("%m-%d_%H%M%S", time.localtime()) + ".csv"
    os.rename(Global_Variables.G_save_file_address_name + ".csv",
              Global_Variables.G_save_file_address_name + suffix_file_name)
    return None

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    MainWindow_csv = MainWindow_slots()
    MainWindow_csv.show()
    sys.exit(app.exec_())
